package cn.virens.common.spring.bean;

import cn.virens.common.util.exception.APIException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SpringBeanProxy<T> implements InvocationHandler {
    private ObjectProvider<T> provider;

    private SpringBeanProxy(ObjectProvider<T> provider) {
        this.provider = provider;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(provider.getIfAvailable(), args);
    }

    @SuppressWarnings("unchecked")
    public static <R> R proxy(Class<R> c, ApplicationContext applicationContext) throws APIException {
        return (R) Proxy.newProxyInstance(c.getClassLoader(), new Class<?>[]{c}, newHander(c, applicationContext));
    }

    private static <R> SpringBeanProxy<R> newHander(Class<R> clazz, ApplicationContext applicationContext) {
        return new SpringBeanProxy<>(applicationContext.getBeanProvider(clazz));
    }

}
